<?php

/**
 * session类
 * 利用cookie实现session
 * @author bing.peng
 *
 */
class Session {
	
	var $userdata;
	var $sess_expiration = 7200;
	var $sess_cookie_name = 'tatu';
	var $cookie_path = '';
	var $time_reference				= 'time';
	var $cookie_domain = '';
	var $now;
	
	function Session($db = null) {
		$this->now = $this->_get_time();
		if( $this->sess_read() ) {
			$this->sess_update();
		}
		else {
			$this->sess_create();
		}
	}
	
	function sess_create() {
		$sessid = '';
		while (strlen($sessid) < 32) {
			$sessid .= mt_rand(0, mt_getrandmax());
		}
		$ip_address = $_SERVER['REMOTE_ADDR'];
		$sessid .= $ip_address;
		
		$this->userdata = array(
							'session_id' 	=> md5(uniqid($sessid, TRUE)),
							'ip_address' 	=> $ip_address,
							'last_activity'	=> $this->now
							);
		
		$this->_set_cookie();
	}
	
	function userdata($item) {
		return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
	}
	
	function set_userdata( $newdata = array(), $newval = '' ) {
		if (is_string($newdata)) {
			$newdata = array($newdata => $newval);
		}
		if (count($newdata) > 0) {
			foreach ($newdata as $key => $val) {
				$this->userdata[$key] = $val;
			}
		}	
		$this->sess_update();
	}
	
	function unset_userdata($key) {
		unset( $this->userdata[$key] );
		$this->sess_update();
	}
	
	function sess_destroy() {
		setcookie( $this->sess_cookie_name, '', ($this->now - 31500000));
	}
	
	function sess_update() {
		$sessid = '';
		while (strlen($sessid) < 32) {
			$sessid .= mt_rand(0, mt_getrandmax());
		}
		$ip_address = $_SERVER['REMOTE_ADDR'];
		$sessid .= $ip_address;
		
		$this->userdata['session_id'] = md5(uniqid($sessid, TRUE));
		$this->userdata['last_activity'] = $this->now;
		$this->_set_cookie();
	}
	
	function sess_read() {
		if( ! isset($_COOKIE[$this->sess_cookie_name]) ) {
			return FALSE;
		}
		
		$data = $this->_unserialize( $_COOKIE[$this->sess_cookie_name] );
		foreach( $data as $key => $val ) {
			$key = base64_decode($key);
			$val = base64_decode($val);
			$this->userdata[$key] = $val;
		}
		
		if( $this->userdata['last_activity'] + $this->sess_expiration < $this->now ) {	
			$this->sess_destroy();
			return FALSE;
		}
		
		return TRUE;
	}
	
	function _set_cookie() {
		$base64_data = array();
		if( !empty( $this->userdata ) ) {
			foreach( $this->userdata as $key=>$value ) {
				$key = base64_encode($key);
				$value = base64_encode($value);
				$base64_data[$key] = $value;
			}
		}
		
		if( !empty( $base64_data ) ) {
			$cookie_data = $this->_serialize($base64_data);	
		}
		else {
			$cookie_data = '';
		}
		$result = setcookie(
			$this->sess_cookie_name, 
			$cookie_data, 
			$this->now + $this->sess_expiration,
			'/'
		);
	}
	
	function _get_time() {
		if (strtolower($this->time_reference) == 'gmt') {
			$now = time();
			$time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
		}
		else {
			$time = time();
		}

		return $time;
	}
	
	function _serialize($data) {
		if (is_array($data)) {
			foreach ($data as $key => $val) {
				$data[$key] = str_replace('\\', '{{slash}}', $val);
			}
		}
		else {
			$data = str_replace('\\', '{{slash}}', $data);
		}

		return serialize($data);
	}
	
	function _unserialize($data) {
		$data = @unserialize( $this->strip_slashes($data) );

		if (is_array($data)) {
			foreach ($data as $key => $val) {
				$data[$key] = str_replace('{{slash}}', '\\', $val);
			}

			return $data;
		}

		return str_replace('{{slash}}', '\\', $data);
	}
	
	function strip_slashes($str) {
		if (is_array($str)) {	
			foreach ($str as $key => $val) {
				$str[$key] = strip_slashes($val);
			}
		}
		else {
			$str = stripslashes($str);
		}
	
		return $str;
	}
		
}

?>